﻿package {
	import flash.display.*;
	import flash.events.*;
    import flash.utils.Timer;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.text.*;
	import flash.filters.BitmapFilterQuality;
	import flash.filters.BlurFilter;
	import flash.geom.Point;
	import flash.net.SharedObject;
	
	
	
	import class_auto;
	import class_weg;
	import ProximityManager;

	public class verkeer extends MovieClip {
		
		
		//init vars
		
		var weg1:class_weg= new class_weg;
		
		var pm:ProximityManager = new ProximityManager(48);
		 
		var GODMODE:Boolean= new Boolean(true);

		//initieel aantal autos
		var NUMAUTOS:int=5;
		var MAXPARTICLES:int=512;
		var MAXSNELHEID:int=5;
		var plife:Number=9;
		//auto array
		var autos:Array = new Array();

		var GameTimer:Timer = new Timer(1000/30); //35 fps
		var AutoTimer:Timer = new Timer(1000/1); //1 sec
		
		//xml shit
		var xmlLoader:URLLoader = new URLLoader();
		var xmlData:XML = new XML();
		
		//editor
		//var the_editor:editor= new editor;
		 var button:Sprite = new Sprite();
         var textLabel:TextField = new TextField();
		 var editor:Sprite = new Sprite();
		 var addP:Boolean =new Boolean( false);
		 var remP:Boolean=new Boolean (false);
		 var toolTip:TextField = new TextField();

		 //DASHBOARD
		 var dashboard:TextField = new TextField();
		 var collisions:uint = 0;
		 var deaths:uint = 0;
		 var flow:Number = 0;
		 var flowGraph: Array = new Array(800);
		 var carGraph:Array = new Array(800);
		 
		 var flowCanvas:Shape = new Shape();
		 var carCanvas:Shape = new Shape();
		 
		
		 
		 //VFX
		 var particles:Array = new Array();
		 var particleSprite:Sprite= new Sprite();
		 var blur:BlurFilter = new BlurFilter();
		 var canvas:Shape = new Shape();
		
		 var canvasbuffer:BitmapData = new BitmapData(800, 600, true, 0x333333);
		 var buffer:Bitmap = new Bitmap(canvasbuffer);

		
	
		public function verkeer():void{
			//init tooltip
				toolTip.multiline=true;
				toolTip.text = "";
				toolTip.wordWrap=true;
             	toolTip.x = mouseX;
             	toolTip.y = mouseY;
				toolTip.scaleX=textLabel.scaleY=1;
             	toolTip.selectable = false;
             	stage.addChild(toolTip);
				
			//init dashboard	
				dashboard.multiline=true;
				dashboard.wordWrap=true;
				dashboard.x=600;
				dashboard.y=50;
				dashboard.autoSize= TextFieldAutoSize.LEFT;
				stage.addChild(dashboard);
				
				for(var i:int=0;i<flowGraph.length;i++){
					flowGraph[i]=0;
					carGraph[i]=NUMAUTOS;
				}
				
			drawButton();
			button.x=400;
			button.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
			//load level and set up cars
			loadLevel();
			
			stage.addEventListener(KeyboardEvent.KEY_DOWN,checkKeysDown);
			stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
			GameTimer.addEventListener(TimerEvent.TIMER, mainGameLoop);
			
			AutoTimer.addEventListener(TimerEvent.TIMER, addtAuto);
			
			
			
			
			blur.blurX = 10;
			blur.blurY = 10;
			blur.quality = BitmapFilterQuality.MEDIUM;
			stage.addChild(flowCanvas);
			stage.addChild(carCanvas);
			
					
					
		}
		
		
		function mainGameLoop(event:TimerEvent):void{
			refreshDashboard();
			
			for(var i:int=0;i<autos.length;i++){
				
				
				if(particles.length<MAXPARTICLES){
					particles.push([autos[i].x+autos[i].width/2,autos[i].y+autos[i].height/2,plife,autos[i].aard]);
				}
				// init vector numbers
				var a:Number;
				var b:Number;
				var len:Number;	
				
				//trace("i: "+i +"/"+autos.length);
				//trace("l: "+autos[i].lijnstuk+ "/"+weg1.wegpunten.length);
				
				//kijk en bereken nieuwe vector volgende wegpunt
				a=autos[i].x-weg1.wegpunten[autos[i].lijnstuk+1][0];
				b=autos[i].y-weg1.wegpunten[autos[i].lijnstuk+1][1];
				len=Math.sqrt(a*a+b*b); //Lennie gaat hier door voor 'afstand tot volgende wegpunt'
				
				if(len<=10&&autos[i].snelheid>2){	//vertraag bij draaing hoek
					autos[i].snelheid*=.8;
				}
				if(len<=4){ //5 marge voor volgende wegstuk
					weg1.wegpunten[autos[i].lijnstuk][2]--; //broadcast removal aan lijnstuk
					if(autos[i].lijnstuk<weg1.wegpunten.length-2){
						autos[i].lijnstuk++;
					}else{
						autos[i].lijnstuk=0;
					}
					weg1.wegpunten[autos[i].lijnstuk][2]++; //broadcast position to lijnstuk
					
				}
			
							
				// bereken vector en broem RIJ!
				
				a=weg1.wegpunten[autos[i].lijnstuk+1][0]-autos[i].x;
				b=weg1.wegpunten[autos[i].lijnstuk+1][1]-autos[i].y;
				len=Math.sqrt(a*a+b*b);			
				autos[i].xvec=a/len;
				autos[i].yvec=b/len;
				
				if(autos[i].snelheid<2&&!autos[i].collision){	//axelereer 1ste versnelling als kan 
					autos[i].snelheid*=1.07;
				}
				if(autos[i].snelheid<MAXSNELHEID&&!autos[i].collision){		//axelereer 2de versnelling als kan
					autos[i].snelheid*=1.02;
				}
				if(!(autos[i].leven)&&autos[i].snelheid<0.2&&!GODMODE){		//KILL DE DODE autos
					//autos[i].leven=false;
					
					deaths++;
					pm.removeItem(autos[i]);
					this.removeChild(autos[i]);
					autos.splice(i,1);
					
					if(!i==autos.length-1){	//volgende auto als niet laatste auto is
						i++;
					}
				}
				
				flow+=autos[i].snelheid;
				
				////////////////	VFX		/////////////////////////////
				canvas.graphics.moveTo(autos[i].x,autos[i].y);			
				autos[i].move_auto();
				
				if (autos[i].collision){ //teken collision trails
					canvas.graphics.lineStyle(1,0x4c4949, 255, true);
					canvas.graphics.lineTo(autos[i].x,autos[i].y);
					canvasbuffer.draw(canvas);
					canvasbuffer.unlock();
					canvas.graphics.clear();
				}

				blur.blurX=autos[i].snelheid*1;
				blur.blurY=autos[i].snelheid*1;
				autos[i].filters = [blur];	
				
				

				
			}
			//particles
			particleSprite.graphics.clear();
			for(i=0;i<particles.length;i++){
				particles[i][2]*=0.9;
				if(particles[i][2]<1){
					particles.splice(i,1);
				}
				if (particles[i][3]){
					particleSprite.graphics.beginFill(0x000000,particles[i][2]/plife);
					}else{
					particleSprite.graphics.beginFill(0xFFFFFF,particles[i][2]/plife);
				} // grey color
             	particleSprite.graphics.drawCircle(particles[i][0]-5,particles[i][1]-5,2);
             	particleSprite.graphics.endFill();
				blur.blurX=blur.blurY=particles[i][2];
				particleSprite.filters = [blur];
			}
			
			
			
			//collisions checken hier:
			pm.refresh();
					
			var count:uint = 0;
			for (i=0; i<autos.length; i++) {
				var neighbors:Array = pm.getNeighbors(autos[i]);
				var l:uint = neighbors.length;
//				autos[i].scaleX = autos[i].scaleY = 0.1+l*0.08*3;
				for (var j:uint=0; j<l; j++) {
					a=autos[i].x-neighbors[j].x;
					b=autos[i].y-neighbors[j].y;
					var c:Boolean = (autos[i].x*autos[i].xvec-neighbors[j].x*neighbors[j].xvec)>0||(autos[i].y*autos[i].yvec-neighbors[j].y*neighbors[j].yvec)>0;
					//a>neighbors[j].xvec&&b>neighbors[j].yvec||a<neighbors[j].xvec&&b<neighbors[j].yvec);
					if (neighbors[j].y != autos[i].y) {
											
						if(Math.sqrt(a*a+b*b)<autos[i].width&&!autos[i].collision){
							collisions++;
							autos[i].collision=true;	//botsen
							if(autos[i].snelheid>neighbors[j].snelheid&&autos[i].snelheid>autos[i].hp&&!GODMODE){
								autos[i].leven=false;
							}else if(!GODMODE&&neighbors[j].snelheid>neighbors[j].hp)	{
								neighbors[j].leven=false;
							}
						}						
						//trace(i+" "+c);
						//trace(i+" : "+neighbors[j].xvec+" x:"+neighbors[j].x);
						
						//remmen voor elkaar
						if(!c&&Math.sqrt(a*a+b*b)<=(28+autos[i].snelheid*3) && !autos[i].aard &&!autos[i].collision&&autos[i].snelheid>0.1){
							autos[i].snelheid*=0.43;	//remmen wit
							
							
						}
						if(!c&&Math.sqrt(a*a+b*b)<=12+autos[i].snelheid && autos[i].aard&&!autos[i].collision &&autos[i].snelheid>0.1){
							autos[i].snelheid*=0.43;	//remmen zwart
							
						}
					}
				}
			}
		}
		
		//DASHBOARD CODE:
		function refreshDashboard():void{
			
			////////bereken en teken de flow grafiek:
			flow=(flow/(autos.length*MAXSNELHEID))*100;
			
			//grafiek met flow
			flowGraph.splice(0,1);
			flowGraph.push(flow);
			
			flowCanvas.graphics.clear();
			//flowCanvas.opaqueBackground = 0xFF0000;
			flowCanvas.graphics.moveTo(0,0);			
			for(var i:int=1;i<flowGraph.length-1;i++){
				flowCanvas.graphics.lineStyle(1,004400, 255, true);
				flowCanvas.graphics.lineTo(i-1,600-flowGraph[i-1]);
			}
			
			///teken auto grafiek
			
			carGraph.splice(0,1);
			carGraph.push(autos.length);
			carCanvas.graphics.clear();
			//flowCanvas.opaqueBackground = 0xFF0000;
			carCanvas.graphics.moveTo(0,600);			
			for(var i:int=1;i<carGraph.length-1;i++){
				carCanvas.graphics.lineStyle(2,0x555000, 255, true);
				carCanvas.graphics.lineTo(i-1,600-(carGraph[i-1]/NUMAUTOS)*100);
			}
			
			dashboard.text=
			 " cars: "+autos.length
			+"\r crashes: "+collisions
			+"\r deaths: "+deaths
			+"\r GODMODE: "+GODMODE 
			+"\r flow: "+String(flow).slice(0,4) + "%"
			+"\r AutoRespawn: "+AutoTimer.delay/1000+" .sec";
			
			flow=0;
		}
		function addtAuto(event:TimerEvent):void{
			addAuto();
		}
		function addAuto():void{
			
			if(autos.length<NUMAUTOS){
				//auto properties
				var locatie:int = Math.random()*weg1.wegpunten.length-1; //lijnstuk
				var aard:Boolean = Boolean(Math.round(Math.random() * 0.5+0.17));
				var snelheid:Number = 1;/*Math.floor(*/ Math.random() * /*((4*int(aard)) - (2*int(aard)))+2+int(aard)*1.5)*/ 2; //snelheid

				//vector numbers
				var len:Number;
				var a:Number; 
				var b:Number;
				
													//aard, leven, baan, lijnstuk, snelheid
				var t_auto:class_auto=new class_auto(Boolean(aard),true,1,locatie,snelheid);
				autos.push(t_auto);
				
				this.addChild(autos[autos.length-1]);
				pm.addItem(autos[autos.length-1]);
				
				autos[autos.length-1].x=weg1.wegpunten[autos[autos.length-1].lijnstuk][0]+Math.random()*100-50;
				autos[autos.length-1].y=weg1.wegpunten[autos[autos.length-1].lijnstuk][1]+Math.random()*100-50;
			}
		}
		
		function addAutos():void{
			//INIT autos / adhv algemene NUMAUTOS:
			var NUMBOUWEN:int = NUMAUTOS - autos.length;
			//trace(NUMBOUWEN,autos.length);
			for(var i:int=0;i<NUMBOUWEN;i++){
				//auto properties
				var locatie:int = Math.random()*weg1.wegpunten.length-1; //lijnstuk
				var aard:Boolean = Boolean(Math.round(Math.random() * 0.5+0.17));
				var snelheid:Number = /*Math.floor(*/ Math.random() * /*((4*int(aard)) - (2*int(aard)))+2+int(aard)*1.5)*/ 2; //snelheid

				//vector numbers
				var len:Number;
				var a:Number; 
				var b:Number;
				
													//aard, leven, baan, lijnstuk, snelheid
				var t_auto:class_auto=new class_auto(Boolean(aard),true,1,locatie,snelheid);
				autos.push(t_auto);
				this.addChild(autos[i]);
				
				//add aan proximity manager
				pm.addItem(autos[i]);

				//broadcast positie naar lijnstuk
				weg1.wegpunten[autos[i].lijnstuk][2]++;
				//trace(weg1.wegpunten[1][2]);
				
				//bereking vector
				a=weg1.wegpunten[autos[i].lijnstuk+1][0]-weg1.wegpunten[autos[i].lijnstuk][0];
				b=weg1.wegpunten[autos[i].lijnstuk+1][1]-weg1.wegpunten[autos[i].lijnstuk][1];
				len=Math.sqrt(a*a+b*b); //squares zo omdat flash ^2 niet hapt
				autos[i].xvec=a/len;
				autos[i].yvec=b/len;
				
				autos[i].x=weg1.wegpunten[autos[i].lijnstuk][0];
				autos[i].y=weg1.wegpunten[autos[i].lijnstuk][1];
				//random start positie
				len=Math.round(Math.random()*300);
				autos[i].x+=(autos[i].xvec*snelheid)*len;
				autos[i].y+=(autos[i].yvec*snelheid)*len;
				
				autos[i].os=autos[i].snelheid;
				
				autos[i].addEventListener(MouseEvent.CLICK, autos[i].onMouseClickEvent);
				autos[i].addEventListener(MouseEvent.MOUSE_OVER, autos[i].onMouseOverEvent);
				autos[i].addEventListener(MouseEvent.MOUSE_OUT, autos[i].onMouseOutEvent);
				
				
			}
			
		}
		function saveLevel():void{
			var so:SharedObject = SharedObject.getLocal("test"); 
			var leveltxt:String=new String();
			so.clear(); //remove previous data
			//prepare level data
			leveltxt+="<weg> \n";
			for(var i:int=0;i<weg1.wegpunten.length-1;i++){
				leveltxt+="<wegpunt> \n";
				leveltxt+="<xx>" + weg1.wegpunten[i][0] + "</xx> \n";
				leveltxt+="<yy>" + weg1.wegpunten[i][1] + "</yy> \n";
				leveltxt+="</wegpunt> \n";
			}
			leveltxt+="</weg>";
			
			//save variables
			so.data.Level = leveltxt; 
			so.data.NUMAUTOS=NUMAUTOS;
			so.data.GODMODE=GODMODE;
			so.data.AUTOINTERVAL=AutoTimer.delay;
			
			so.flush()	//write data to cookie
		}
		function loadLevel():void{
			loadcookie();
		}
		
		function loadcookie():void{
			var so:SharedObject = SharedObject.getLocal("test"); 
			if (so.size == 0) 
			{ 
				// cookie  doesn't exist. 
				// so load default level XML
				// and save that as cookie
				xmlLoader.addEventListener(Event.COMPLETE, LoadLevelXML);
				xmlLoader.load(new URLRequest("level.xml"));
				saveLevel();

			}else{
				//laad level data met xml structuur uit cookie:
				xmlData = new XML(so.data.Level);
				
				for(var i:int=0;i<xmlData.wegpunt.length();i++){
					weg1.add_weg(xmlData.wegpunt[i].xx, xmlData.wegpunt[i].yy);
				}
				
				weg1.add_weg(xmlData.wegpunt[0].xx, xmlData.wegpunt[0].yy);
				weg1.draw_weg();	//teken weg
				
				//laad de rest van variables uit cookie:
				NUMAUTOS=so.data.NUMAUTOS;
				GODMODE=so.data.GODMODE;
				AutoTimer.delay=so.data.AUTOINTERVAL;
				
				//init autos& starting conditions
				init();
				}
		}
		function LoadLevelXML(e:Event):void {
			xmlData = new XML(e.target.data);
						
			for(var i:int=0;i<xmlData.wegpunt.length();i++){
				weg1.add_weg(xmlData.wegpunt[i].xx, xmlData.wegpunt[i].yy);
			}
			
			weg1.add_weg(xmlData.wegpunt[0].xx, xmlData.wegpunt[0].yy);
			
			weg1.draw_weg();
		
			
			//init autos& starting conditions
			init();
			
		}
		function init():void{
		canvas.cacheAsBitmap = true;
		//canvas.opaqueBackground = 0x333333;
//		addChild(canvas);
		addChild(buffer);		
		this.addChild(weg1);
			//init autos
			addAutos();
			//start game
			GameTimer.start();
			
			AutoTimer.start();
			
			
			addChild(particleSprite);
            addChild(button);
			addChild(editor);

			
			
		}
		//KEYBOARD INPUT:
		function checkKeysDown(event:KeyboardEvent):void{
		trace("You pressed key: "+event.keyCode);			
			if (event.keyCode == 187) { //voeg auto aan queue toe met +
				NUMAUTOS++;
			}
			if (event.keyCode == 32) { //bouw autos in queue
				addAuto();
				
			}
			if (event.keyCode == 71) { //TOGLE GODMODE
				GODMODE=!GODMODE;
			}
			if (event.keyCode == 221){	// "]" increase AutoTimer.delay
				AutoTimer.delay+=(1000*.25);
			}
			if (event.keyCode == 219){	// "]" increase AutoTimer.delay
				if(AutoTimer.delay>(1000/2)){
					AutoTimer.delay-=(1000*0.25);
				}
			}
			if (event.keyCode == 16 && textLabel.text=="play" ){
				remP=true;
				toolTip.visible=true;
				toolTip.x=mouseX+25;
				toolTip.y=mouseY;
				toolTip.text="remove a corner";
			}
			if (event.keyCode == 17 && textLabel.text=="play" ) { //zet add punten aan
				addP=true;
				toolTip.visible=true;
				toolTip.x=mouseX+25;
				toolTip.y=mouseY;
				toolTip.text="add a corner to the road";
				
			}
			

		}
		private function keyUpHandler(event:KeyboardEvent):void {
            if (event.keyCode == 17 && textLabel.text=="play"){
				addP=false;
				toolTip.visible=false;
			}
			if (event.keyCode == 16 && textLabel.text=="play"){
				remP=false;
				toolTip.visible=false;
			}
			//trace("keyUpHandler: " + event.keyCode);
        }

		//EDITOR CODE
		    function drawButton():void {
             
             button.graphics.clear();
             button.graphics.beginFill(0xffffff); // grey color
             button.graphics.drawRect(-1200, 0, 2200, 20);
             button.graphics.endFill();
             textLabel.text = "edit";
             textLabel.x = 10;
             textLabel.y = 5;
             textLabel.selectable = false;
             button.addChild(textLabel);
			 
         }
		     private function mouseDownHandler(event:MouseEvent):void {
			if(textLabel.text=="edit"){
				textLabel.text="play";
				
				
				GameTimer.stop();	//pause de game
				AutoTimer.stop();
				
				show_editor();
				
			}else{
				textLabel.text="edit";
				
				
				trace("////////////////LEVEL DATA//////////////////////");
				trace("<weg>");
				for(var i:int=0;i<weg1.wegpunten.length-1;i++){
					trace("<wegpunt>");
					trace("<xx>" + weg1.wegpunten[i][0] + "</xx>");
					trace("<yy>" + weg1.wegpunten[i][1] + "</yy>");
					trace("</wegpunt>");
				}
				trace("</weg>");
				trace("////////////////LEVEL DATA//////////////////////");
				
				
				saveLevel();
				
				//remove alle editor GFX
				editor.removeChildAt(0);
				
				//zet alle autos op juiste lijnstuk
				for(var m:int=0;m<autos.length;m++){
					
					if(autos[m].lijnstuk>=weg1.wegpunten.length-1){
						autos[m].lijnstuk=0;
						
					}
				}
				GameTimer.start(); //start timer weer
				AutoTimer.start();
			}
				
         }
		function show_editor():void{
			var wegpunten: Sprite = new Sprite();
			for(var i:int=0;i<weg1.wegpunten.length-1;i++){
				var btn_hkpnt: Sprite= new Sprite();
				
				btn_hkpnt.graphics.beginFill(0xFFCC00);
				btn_hkpnt.graphics.drawCircle(0, 0, 10);

				btn_hkpnt.x=weg1.wegpunten[i][0];
				btn_hkpnt.y=weg1.wegpunten[i][1];
				
				btn_hkpnt.addEventListener(MouseEvent.MOUSE_DOWN, sleepPunt);
				btn_hkpnt.addEventListener(MouseEvent.MOUSE_UP, zetPunt);
				
				wegpunten.addChildAt(btn_hkpnt,i);
				editor.addChildAt(wegpunten,0);
			}
			
		}
		
		function sleepPunt(evt:MouseEvent):void{
			//trace(evt.target.parent.getChildAt(0).x);
			var j:Array = new Array();
			var n:int =  0;
			var i:int=evt.target.parent.getChildIndex(evt.target);
			
			if(remP){ //if SHIFT (remove punt)
				
				j=weg1.wegpunten;
				j.splice(i,1);
				weg1.wegpunten=j;
				
				
			}
			if(addP){ //if CTR
				//trace("zet p");
				weg1.wegpunten.splice(i,0,[weg1.wegpunten[i][0]+0,weg1.wegpunten[i][1]-25]);
				//trace(evt.target.parent.getChildIndex(evt.target)); //SELECTED POINT
				
				
			}if(!remP&&!addP){ //anders sleep
				evt.target.startDrag(true);
			}
			
		
		}
		function zetPunt(evt:MouseEvent):void{
			if(!addP&&!remP){
				evt.target.stopDrag();
				for(var i:int=0;i<weg1.wegpunten.length-1;i++){
					weg1.wegpunten[i][0]=evt.target.parent.getChildAt(i).x;
					weg1.wegpunten[i][1]=evt.target.parent.getChildAt(i).y;
				}
				//weg1.wegpunten[weg1.wegpunten,length-1][0]= weg1.wegpunten[0][0];
				//weg1.wegpunten[weg1.wegpunten,length-1][1]= weg1.wegpunten[0][1];
				
			}
			weg1._update();
			editor.removeChildAt(0);
			show_editor();
		}
		
		
	}
	
}
